import java.awt.Frame;
import java.io.*;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.TimeZone;
import java.text.FieldPosition;
import java.text.ParseException;
import java.text.ParsePosition;
import java.text.SimpleDateFormat;

import javax.swing.JOptionPane;

/**
 * Class to create .ics files from RFC2445 specifications.
 */

public class Creation {
	
	protected Frame frame = new Frame();
	protected String version = "VERSION:2.0"; //sets calendar version to 2.0
	protected String classification = "CLASS:PUBLIC"; //default classification is PUBLIC
	protected String comment = null; //holds comment here
	protected String geoPosition = null; //holds geographical position here
	protected String location = null; //holds location of event
	protected String resource = null; //holds string list of resources
	protected Date startDate = null; //used to compare to end date
	protected Date startTime = null; //used to compare to end time
	protected Date endDate = null; //used to compare to start date
	protected Date endTime = null; //used to compare to start time
	protected String dtStart = null; //holds final start date-time formated string
	protected String dtEnd = null; //holds final end date-time formatted string
	protected String timezone = null; //holds timezone identifier
	/*
	 * sets version string as PUBLIC, PRIVATE or CONFIDENTIAL
	 * Parameter will take ints from 0 to 2
	 * PUBLIC = 0, PRIVATE = 1, CONFIDENTIAL = 2
	 */
	public void classification(int state) {
		if (state == 0) this.classification = "CLASS:PUBLIC";
		else if (state == 1) this.classification = "CLASS:PRIVATE";
		else if (state == 2) this.classification = "CLASS:CONFIDENTIAL";
	}
	
	//this method inputs a comment into the .ics file and takes a String as the comment to be entered
	public void comment(String comment) {
		if (comment == null);
		else if (comment != null) this.comment = "COMMENT:"+comment; //concatenates String comment onto "COMMENT:"
	}
	
	//this method sets geographical positions by taking float values of latitude and longitude
	public void geoPosition(float latitude, float longitude) {
		if (latitude > 90.000000f || latitude < -90.000000f) {
			geoPosition = null;
        	JOptionPane.showMessageDialog(frame, "Latitude is out of bounds!");
		} else if (longitude > 180.000000f || longitude < -180.000000f) {
			geoPosition = null;
        	JOptionPane.showMessageDialog(frame, "Longitude is out of bounds!");
		} else if ((latitude <= 90.000000f && latitude >= -90.000000f) && (longitude <= 180.000000f && longitude >= -180.000000f)) {
			float temp = latitude;
			float temp2 = longitude;
			latitude = (float) ((1000000 * temp) / 1000000);
			longitude = (float) ((1000000 * temp2) / 1000000);
			geoPosition = "GEO:" + latitude + ";" + longitude;
		} else {
			geoPosition = null;
        	JOptionPane.showMessageDialog(frame, "Error: Geographical Positioning.");
		}
		
	}
	
	public void location(String loc) {
		if (loc == null) {
			//do nothing
		}else if (loc != null) {
			this.location = "LOCATION:" + loc;
		}
	}
	
	/*
	 * accepts list of resources separated by comma
	 * may be implemented using an array or some collection
	 */
	public void resources(String res) {
		if (res == null) {
			//do nothing
		} else if (res != null) {
			this.resource = res;
		}
	}
	
	//sets date and time for event start
	public void dtStart(int month, int day, int year, int hour, int min, int sec) {
		//tests if date is valid
		try {
			SimpleDateFormat sdf = new SimpleDateFormat("MM/dd/yyyy");
			sdf.setLenient(false);
			startDate = sdf.parse(month + "/" + day + "/" + year);
        } catch (ParseException e) {
        	JOptionPane.showMessageDialog(frame, "Invalid Starting Date!.");
        	dtStart = null; //resets value
        } catch (IllegalArgumentException e) {
        	JOptionPane.showMessageDialog(frame, "Invalid Starting Date!.");
        	dtStart = null; //resets value
        }
		//tests if time is valid (hours are 0 to 23 in value)
		try {
			SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss");
			sdf.setLenient(false);
			startTime = sdf.parse(hour + ":" + min + ":" + sec);
			
			//creating DTSTART string here
			dtStart = "DTSTART:" + year;
			
			if (month < 10) dtStart = dtStart + "0" + month;
			else dtStart = dtStart + month;
			
			if (day < 10) dtStart = dtStart + "0" + day;
			else dtStart = dtStart + day;
			
			dtStart = dtStart + "T";
			
			if(hour < 10) dtStart = dtStart + "0" + hour;
			else dtStart = dtStart + hour;
			
			if(min < 10) dtStart = dtStart + "0" + min;
			else dtStart = dtStart + min;
			
			if(sec < 10) dtStart = dtStart + "0" + sec;
			else dtStart = dtStart + sec;
			
			dtStart = dtStart + "Z";
			
        } catch (ParseException e) {
        	JOptionPane.showMessageDialog(frame, "Invalid Starting Time!.");
        	dtStart = null; //resets value
        } catch (IllegalArgumentException e) {
        	JOptionPane.showMessageDialog(frame, "Invalid Starting Time!.");
        	dtStart = null; //resets value
        }
		

	}
	
	//sets end time for event but checks that start time exists and that it is after the start time
	public void dtEnd(int month, int day, int year, int hour, int min, int sec) {
		//tests if date is valid
		try {
			SimpleDateFormat sdf = new SimpleDateFormat("MM/dd/yyyy");
			sdf.setLenient(false);
			endDate = sdf.parse(month + "/" + day + "/" + year);
        } catch (ParseException e) {
        	JOptionPane.showMessageDialog(frame, "Invalid Ending Date!.");
        	dtEnd = null; //resets value
        } catch (IllegalArgumentException e) {
        	JOptionPane.showMessageDialog(frame, "Invalid Ending Date!.");
        	dtEnd = null; //resets value
        }
		//tests if time is valid
		try {
			SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss");
			sdf.setLenient(false);
			endTime = sdf.parse(hour + ":" + min + ":" + sec);
			
			//checks if start date-time is before end date-time
			if (startTime.compareTo(endTime) < 0 && startDate.compareTo(endDate) <= 0) {
				//creating DTSTART string here
				dtEnd = "DTEND:" + year;
				
				if (month < 10) dtEnd = dtEnd + "0" + month;
				else dtEnd = dtEnd + month;
				
				if (day < 10) dtEnd = dtEnd + "0" + day;
				else dtEnd = dtEnd + day;
				
				dtEnd = dtEnd + "T";
				
				if(hour < 10) dtEnd = dtEnd + "0" + hour;
				else dtEnd = dtEnd + hour;
				
				if(min < 10) dtEnd = dtEnd + "0" + min;
				else dtEnd = dtEnd + min;
				
				if(sec < 10) dtEnd = dtEnd + "0" + sec;
				else dtEnd = dtEnd + sec;
				
				dtEnd = dtEnd + "Z";
				
			} else {
	        	JOptionPane.showMessageDialog(frame, "Ending time is before starting time!.");
				dtEnd = null; //if time is wrong DTEND is not added
			}
			
        } catch (ParseException e) {
        	JOptionPane.showMessageDialog(frame, "Invalid Ending Time!.");
        	dtEnd = null; //resets value
        } catch (IllegalArgumentException e) {
        	JOptionPane.showMessageDialog(frame, "Invalid Ending Time!.");
        	dtEnd = null; //resets value
        }
	}
	
	public void timeZoneId(String id) {
		timezone = "TZID:" + TimeZone.getTimeZone(id).getID();
	}
	
	public void createFile() throws IOException{
		FileWriter stream = null;
		BufferedWriter output = null;
		
		File file = new File("calendar.ics");
		  if(!file.exists()){
			  file.createNewFile();
			  stream = new FileWriter("calendar.ics");
			  output = new BufferedWriter(stream);
			  
			  output.write("BEGIN:VCALENDAR" + "\n"); //needed to begin calendar
			  
			  if (classification != null) output.write(classification + "\n"); //writes classification to .ics file if value is not null
			  
			  output.write("BEGIN:VTIMEZONE" + "\n"); //writes BEGIN:VTIMEZONE required for timezone identifier
			  
			  output.write(timezone + "\n"); //writes timezone
			  
			  output.write("END:VTIMEZONE" + "\n"); //ends VTIMEZONE
			  
			  output.write(version + "\n"); //writes version to .ics file
			  
			  output.write("BEGIN:VEVENT" + "\n"); //writes that event has begun
			  			  
			  if (comment != null) output.write(comment + "\n"); //writes classification to .ics file if value is not null
			  
			  if (geoPosition != null) output.write(geoPosition + "\n"); //writes geographical position in event file
			  
			  if (location != null) output.write(location + "\n"); //writes location in event file
			  			  			  
			  if (dtStart == null) {
				  output.flush();
				  output.close();
				  JOptionPane.showMessageDialog(frame, "Aborting: Start Date-Time Invalid!.");
			  } else output.write(dtStart + "\n"); //writes start time of event

			  if (dtEnd != null) output.write(dtEnd + "\n"); //writes end time of event if there is one
			  
			  output.write("END:VEVENT" + "\n");
			  output.write("END:VCALENDAR");
			  output.close();
		  }
		  
		  
	}
	/**
	 * THIS IS USED TO TEST THE CREATION
	public static void main(String[] args) throws IOException {
		Creation export = new Creation(); //test object
		
		export.classification(0); //sets classification to PUBLIC
		export.timeZoneId("GMT");
		export.comment("This is far from done!"); //sets a comment
		export.geoPosition((float)89.11111111, (float)179.11111111);
		export.location("UH");
		export.dtStart(4, 29, 2012, 22, 0, 0);
		export.dtEnd(4, 29, 2012, 23, 0, 0);
		export.createFile(); //tests createFile() method
	}
	*/
	
	
}
